package com.aiden.app.common.base

import android.Manifest
import android.app.Activity
import android.arch.lifecycle.Lifecycle
import android.arch.lifecycle.LifecycleRegistry
import android.content.ComponentCallbacks
import android.content.ComponentName
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.drawable.AnimationDrawable
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkRequest
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.support.annotation.DrawableRes
import android.support.annotation.StringRes
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.*
import android.widget.EditText
import android.widget.ImageButton
import android.widget.TextView
import com.aiden.app.common.BuildConfig
import com.aiden.app.common.R
import com.aiden.app.common.constant.PrefConstants
import com.aiden.app.common.extension.*
import com.aiden.app.common.util.LogUtils
import com.aiden.app.common.util.NetworkUtil
import com.aiden.app.common.util.NotchUtils
import com.aiden.app.common.util.NoticeDialog
import com.aiden.app.common.widget.dialog.LoadingDialog
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.tbruyelle.rxpermissions2.RxPermissions
import com.umeng.analytics.MobclickAgent
import kotlinx.android.synthetic.main.activity_base.*
import kotlinx.android.synthetic.main.base_page_error.*
import kotlinx.android.synthetic.main.empty_view.*
import kotlinx.android.synthetic.main.error_view.*
import kotlinx.android.synthetic.main.loading_view.*
import kotlinx.android.synthetic.main.net_error_view.*
import org.greenrobot.eventbus.EventBus
import java.util.*

open class BaseActivity : AppCompatActivity() {
    protected val REQEUST_CODE_PERMISSION = 0x100

    protected val MAX_TITLE_LENGTH = 8

    protected lateinit var mContext: Activity
    private var mRxPermissions: RxPermissions? = null
    private lateinit var mPermissions: Array<String>
    private lateinit var mPermissionListener: OnRequestPermissionListener
    private var lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
    private var lifecycleObservers: ArrayList<LifecycleCallback> = ArrayList()
    protected lateinit var toolbar: Toolbar
    private lateinit var ibLeft: ImageButton
    protected lateinit var ibRight: ImageButton
    protected lateinit var tvTitle: TextView
    protected lateinit var tvRight: TextView
    private lateinit var mContentView: View
    private lateinit var loadingDialog: BasePopupView
    private var isRequestNet = false

    private var animationDrawable: AnimationDrawable? = null
    protected open fun initView() {}
    protected open fun initListener() {}
    protected open fun initIntentData() {}
    protected open fun loadData() {
        showLoading(true)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        setDensity()
        super.setContentView(R.layout.activity_base)
        mContext = this
        loadingDialog = XPopup.Builder(mContext).hasShadowBg(false).asCustom(LoadingDialog(mContext))
        val toolbarView = inflate(R.layout.layout_toolbar, null)
        toolbar = toolbarView.findViewById(R.id.toolbar)
//        setSupportActionBar(toolbar)
        ibLeft = toolbarView.findViewById(R.id.ib_left)
        ibRight = toolbarView.findViewById(R.id.ib_right)
        tvTitle = toolbarView.findViewById(R.id.tv_title)
        tvRight = toolbarView.findViewById(R.id.tv_right)

        ibLeft.setOnClickListener { onLeftClicked() }
        ibRight.onClick { onRightButtonClicked() }
        tvRight.onClick { onRightTextClicked() }
    }

    override fun setContentView(layoutResID: Int) {
        setContentView(View.inflate(mContext, layoutResID, null))
        setStatusBarUpperAPI21()

    }

    open fun isUseParentErrorView(): Pair<Boolean, Int?> {
        return Pair(true, null)
    }

    /**
     * 是否使用默认标题栏，如需自定义标题栏，重写该方法
     */
    open fun isUseDefaultToolBar(): Pair<Boolean, View?> {
        return Pair(true, null)
    }

    override fun setContentView(view: View?) {
        mContentView = view!!
        fl_multiple.addView(mContentView, 0)
        mContentView = if (isUseParentErrorView().first) { // 使用了父类的 ErrorView
            val errorView = LayoutInflater.from(this).inflate(R.layout.base_page_error, null)
            fl_multiple.addView(errorView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
            view
        } else {
            findViewById(isUseParentErrorView().second!!)
        }
        NotchUtils.getNotchHeight(this, object : NotchUtils.OnGetNotchHeightListener {
            override fun getNotch(notchHeight: Int) {
                LogUtils.e(TAG, "notch height = $notchHeight")
                putInt(PrefConstants.NotchHeight, notchHeight)
                if (notchHeight > 0) {
                    if (isUseDefaultToolBar().first) {
                        toolbar.setPadding(0, notchHeight, 0, 0)
                    } else {
                        isUseDefaultToolBar().second?.setPadding(0, notchHeight, 0, 0)
                    }
                }
                ll_content.addView(toolbar, 0)
            }
        })
        initIntentData()
        initView()
        initListener()
        loadData()

        if (isRequestNet && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            connectivityManager.requestNetwork(NetworkRequest.Builder().build(), object : ConnectivityManager.NetworkCallback() {
                override fun onAvailable(network: Network?) {
                    runOnUiThread {
                        onNetAvailable()
                    }
                }

                override fun onLost(network: Network?) {
                    runOnUiThread {
                        onNetDisconnect()
                    }
                }
            })
        }
    }

    override fun onResume() {
        super.onResume()
        MobclickAgent.onResume(this)
    }

    override fun onPause() {
        super.onPause()
        MobclickAgent.onPause(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        removeObservers()
    }

    fun addLifecycleObserver(lifecycleCallback: LifecycleCallback) {
        if (!lifecycleObservers.contains(lifecycleCallback)) {
            lifecycleObservers.add(lifecycleCallback)
        }
        lifecycleRegistry.addObserver(lifecycleCallback)
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQEUST_CODE_PERMISSION) {
            // 从权限设置页面返回，重新请求权限
            requestPermission(permissions = *mPermissions, listener = mPermissionListener)
        }
    }

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        ev?.let {
            if (it.action == MotionEvent.ACTION_DOWN) {
                val v = currentFocus
                if (shouldHideInputMethod(v, ev)) {
                    hideInputMethod()
                }
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    private fun shouldHideInputMethod(v: View?, event: MotionEvent): Boolean {
        v?.apply {
            if (v is EditText) {
                val arr = intArrayOf(0, 0)
                this.getLocationInWindow(arr)
                val left = arr[0]
                val top = arr[1]
                val bottom = top + this.height
                val right = left + this.width
                return !(event.x > left && event.x < right && event.y > top && event.y < bottom)
            }
            return false
        }
        return false
    }

    /**
     * 设置标题栏
     * @author aiden@tronsis.com
     * @date 2018/8/21 17:21
     * @param showLeft 是否显示标题左边按钮（返回按钮），默认显示
     * @param title 标题
     * @param leftBtnRes 左边按钮背景图片资源id
     * @param rightBtnRes 右边按钮背景图片资源id
     * @param rightText 右边文字
     * @param rightTextRes 右边文字资源
     */
    protected fun setTitle(showLeft: Boolean = true, title: String?, titleColor: Int? = null, @DrawableRes leftBtnRes: Int = -1, @DrawableRes rightBtnRes: Int = -1, rightText: String? = "", @StringRes rightTextRes: Int = -1, rightTextColor: Int? = null, @DrawableRes titleBackgroundRes: Int = -1) {
        if (!showLeft) {
            ibLeft.visibility = View.GONE
        }
        if (title.isNotNil()) {
            tvTitle.text = title
            if (titleColor != null) {
                tvTitle.setTextColor(titleColor)
            }
        }
        if (leftBtnRes != -1) {
            ibLeft.setImageResource(leftBtnRes)
        }
        if (rightBtnRes != -1) {
            ibRight.setImageResource(rightBtnRes)
            ibRight.visibility = View.VISIBLE
        }
        if (rightText.isNotNil()) {
            tvRight.text = rightText
            tvRight.visibility = View.VISIBLE
            if (rightTextColor != null) {
                tvRight.setTextColor(rightTextColor)
            }
        }
        if (rightTextRes != -1) {
            tvRight.setText(rightTextRes)
            tvRight.visibility = View.VISIBLE
            if (rightTextColor != null) {
                tvRight.setTextColor(rightTextColor)
            }
        }
        if (titleBackgroundRes != -1) {
            toolbar.setBackgroundResource(titleBackgroundRes)
        }
    }

    protected fun hideToolbar() {
        toolbar.visibility = View.GONE
    }

    open fun onLeftClicked() {
        finish()
    }

    open fun onRightButtonClicked() {

    }

    open fun onRightTextClicked() {

    }

    override fun finish() {
        hideInputMethod()
        super.finish()
    }

    protected fun showContent() {
        mContentView.setVisible(true)
        error_view.setVisible(false)
        empty_view.setVisible(false)
        loading_view.setVisible(false)
        net_error_view.setVisible(false)
        dismissLoadingDialog()
        stopLoading()
    }

    fun showLoading(isUsePageLoading: Boolean = false, emptyHint: String = "暂无数据") {
        if (isUsePageLoading) {
            mContentView.setVisible(false)
            error_view.setVisible(false)
            empty_view.setVisible(false)

            loading_view.setVisible(true)

            net_error_view.setVisible(false)
            if (animationDrawable == null) {
                iv_loading.setImageResource(R.drawable.comm_refresh)
                animationDrawable = iv_loading.drawable as AnimationDrawable
            }
            animationDrawable?.start()
        } else {
            showLoadingDialog(emptyHint)
        }
    }

    fun isShowEmptyOrNot(isNotEmpty: Boolean, emptyHint: String = "暂无数据") {
        if (isNotEmpty) {
            showContent()
        } else {
            showEmpty(emptyHint)
        }
    }

    open fun onNetAvailable() {
    }

    open fun onNetDisconnect() {
        showNoNetwork { loadData() }
    }

    protected fun showError(func: () -> Unit) {
        if (NetworkUtil.isNetAvailable(this)) {
            mContentView.setVisible(false)
            error_view.setVisible(true)
            empty_view.setVisible(false)
            loading_view.setVisible(false)
            net_error_view.setVisible(false)
            stopLoading()
            dismissLoadingDialog()
            error_retry_view.onClick {
                func()
            }
        } else {
            showNoNetwork(func)
        }
    }

    protected open fun showNoNetwork(func: () -> Unit) {
        mContentView.setVisible(false)
        error_view.setVisible(false)
        empty_view.setVisible(false)
        loading_view.setVisible(false)
        net_error_view.setVisible(true)
        ll_net_error.onClick {
            func()
        }
        stopLoading()
        dismissLoadingDialog()
    }

    protected fun showEmpty(notice: String = "暂无数据") {
        mContentView.setVisible(false)
        error_view.setVisible(false)
        empty_view.setVisible(true)
        tv_notice.text = notice
        loading_view.setVisible(false)
        stopLoading()
        dismissLoadingDialog()
    }

    protected fun stopLoading() {
        if (animationDrawable != null && animationDrawable?.isRunning!!) {
            animationDrawable?.stop()
        }
    }

    protected fun showLoadingDialog(title: String = "") {
        loadingDialog.show()
    }

    protected fun dismissLoadingDialog() {
        if (!loadingDialog.isDismiss) {
            loadingDialog.dismiss()
        }
    }

    protected fun requestPermission(vararg permissions: String, listener: OnRequestPermissionListener) {
        if (mRxPermissions == null) {
            mRxPermissions = RxPermissions(this)
        }
        mPermissionListener = listener

        mPermissions = permissions as Array<String>
        val disposable = mRxPermissions!!.requestEachCombined(*permissions).subscribe { permission ->
            if (permission.granted) {
                // 获取到所有权限
                listener.onGranted()
            } else if (permission.shouldShowRequestPermissionRationale) {
                // 有至少一个权限被拒绝且没有勾选不再提示
                listener.onDenied()
            } else {
                // 有至少一个权限被拒绝且勾选不再提示
                listener.onDenied()
                showPermissionNoticeDialog()
            }
        }

    }

    protected fun requestEachPermission(vararg permissions: String, listener: OnRequestEachPermissionListener) {
        if (mRxPermissions == null) {
            mRxPermissions = RxPermissions(this)
        }

        mPermissions = permissions as Array<String>
        val disposable = mRxPermissions!!.requestEach(*permissions).subscribe { permission ->
            if (permission.granted) {
                listener.onGranted(mPermissions.indexOf(permission.name))
            } else if (permission.shouldShowRequestPermissionRationale) {
                listener.onDenied(mPermissions.indexOf(permission.name))
            } else {
                listener.onDenied(mPermissions.indexOf(permission.name))
                showPermissionNoticeDialog()
            }
        }
    }

    /**
     * 拒绝并不再提示的权限 提示去设置页面设置
     */
    protected fun showPermissionNoticeDialog() {
        NoticeDialog.confirm(mContext, message = string(R.string.permission_notice), title = "提示", positiveText = "设置", onPositiveClickListener = DialogInterface.OnClickListener { dialog, which ->
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            val uri: Uri = Uri.fromParts("package", packageName, null)
            intent.data = uri
            startActivityForResult(intent, REQEUST_CODE_PERMISSION)
        })
    }

    protected fun setDarkStatusBar() {
        // 设置状态栏元素的颜色为黑色
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            val uiOptions = window.decorView.systemUiVisibility
            val curr = uiOptions or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
            window.decorView.systemUiVisibility = curr
        }
    }

    protected fun setLightStatusBar() {
        // 设置状态栏元素的颜色为白色
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            val uiOptions = window.decorView.systemUiVisibility
            val curr = uiOptions and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
            window.decorView.systemUiVisibility = curr
        }
    }

    protected fun setToolbarBackground(@DrawableRes drawableRes: Int) {
        toolbar.setBackgroundResource(drawableRes)
    }

    protected fun setToolbarColor(color: Int) {
        toolbar.setBackgroundColor(color)
    }

    protected fun showInputMethod(editText: EditText) {
        val timer = Timer()
        timer.schedule(object : TimerTask() {
            override fun run() {
                inputMethodManager?.showSoftInput(editText, 0)
            }
        }, 200)
    }

    fun hideInputMethod() {
        inputMethodManager?.hideSoftInputFromWindow(currentFocus?.windowToken, 0)
    }

    protected fun registerEventBus() {
        EventBus.getDefault().register(this)
    }

    protected fun unregisterEventBus() {
        EventBus.getDefault().unregister(this)
    }

    protected fun dontListenNetWork() {
        isRequestNet = false
    }

    protected fun enableActivityIcon() {
        packageManager.setComponentEnabledSetting(ComponentName(baseContext, "com.dahu.app.ui.Activity"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
        packageManager.setComponentEnabledSetting(ComponentName(baseContext, "com.dahu.app.ui.Normal"), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
    }

    protected fun enableNormalIcon() {
        packageManager.setComponentEnabledSetting(ComponentName(baseContext, "com.dahu.app.ui.Normal"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP)
        packageManager.setComponentEnabledSetting(ComponentName(baseContext, "com.dahu.app.ui.Activity"), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
    }

    private fun setStatusBarUpperAPI21() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            window.statusBarColor = Color.TRANSPARENT
            val content = findViewById<ViewGroup>(Window.ID_ANDROID_CONTENT)
            val childView: View? = content.getChildAt(0)
            if (childView != null) {
                childView.fitsSystemWindows = false
            }
        } else {
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
        }
    }

    private var mFontScaledDensity: Float = 0f
    private var mOldDensity: Float = 0f

    /**
     * 今日头条屏幕适配，修改density
     */
    private fun setDensity() {
        val designWidth = BuildConfig.DESIGN_WIDTH

        val appDisplayMetrics = BaseApplication.INSTANCE.resources.displayMetrics

        if (mOldDensity == 0f) {
            mOldDensity = appDisplayMetrics.density
            mFontScaledDensity = appDisplayMetrics.scaledDensity
            BaseApplication.INSTANCE.registerComponentCallbacks(object : ComponentCallbacks {
                override fun onLowMemory() {
                }

                override fun onConfigurationChanged(newConfig: Configuration?) {
                    if (newConfig != null && newConfig.fontScale > 0) {
                        mFontScaledDensity = BaseApplication.INSTANCE.resources.displayMetrics.scaledDensity
                    }
                }
            })
        }
        val targetDensity = (appDisplayMetrics.widthPixels / designWidth).toFloat()
        val targetDensityDpi = (160 * targetDensity).toInt()
        val targetScaleDensity = targetDensity * (mFontScaledDensity / mOldDensity)

        appDisplayMetrics.density = targetDensity
        appDisplayMetrics.densityDpi = targetDensityDpi
        appDisplayMetrics.scaledDensity = targetScaleDensity

        val displayMetrics = resources.displayMetrics
        displayMetrics.density = targetDensity
        displayMetrics.scaledDensity = targetScaleDensity
        displayMetrics.densityDpi = targetDensityDpi
    }

    private fun removeObservers() {
        for (observer in lifecycleObservers) {
            lifecycleRegistry.removeObserver(observer)
        }
        lifecycleObservers.clear()
    }

    fun callPhone(phoneNumber: String) {
        requestPermission(Manifest.permission.CALL_PHONE, listener = object : OnRequestPermissionListener {
            override fun onGranted() {
                val number = "tel:$phoneNumber"
                val intent = Intent(Intent.ACTION_DIAL)
                intent.data = Uri.parse(number)
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                startActivity(intent)
            }

            override fun onDenied() {
                showPermissionNoticeDialog()
            }
        })
    }
}